package com.sqx.modules.health.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sqx.modules.health.common.Constants;
import com.sqx.modules.health.common.Result;
import com.sqx.modules.health.entity.*;
import com.sqx.modules.health.service.INcgDeviceWatchService;
import com.sqx.modules.health.service.ISaihongService;
import com.sqx.modules.health.service.IWarningService;
import com.sqx.modules.health.service.NcgWatchService;
import com.sqx.modules.health.utils.MyBeanUtil;
import com.sqx.modules.health.utils.ObjectUtils;
import com.sqx.modules.health.vo.NcgWatchVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import java.time.LocalDateTime;
import java.util.*;

/**
 * 前端控制器
 *
 * @author gxy
 * @since 2022-04-19
 */
@Slf4j
@Api(tags = "手表服务接口(对接数据接口)")
@RestController
@RequestMapping("/health/ncgWatch")
public class NcgWatchController {
    @Autowired
    private NcgWatchService ncgWatchService;
    @Autowired
    private IWarningService warningService;
    @Autowired
    private INcgDeviceWatchService deviceWatchService;
    @Autowired
    private ISaihongService saihongService;

    @Transactional
    @ApiOperation(value = "获取结果并新增设备信息(所有)", notes = "获取结果并新增设备信息(所有)")
    @PostMapping("/getParam")
    public Result save(@RequestBody Map params) throws Exception {
        log.info("save method start ====> params:{}", params);
        if (!params.containsKey("imei")){
            return Result.error(Constants.CODE_500, "IMEI必填");
        }
        if (StringUtils.isBlank((String) params.get("imei"))){
            return Result.error(Constants.CODE_500, "IMEI不能为空");
        }

        if (params.containsKey("locationInfo") || params.containsKey("alarmInfo")){
            NcgWatchVO vo = JSONObject.parseObject(JSONObject.toJSONString(params), NcgWatchVO.class);
            return saveAll(vo);
        } else {
            NcgWatch watch = JSONObject.parseObject(JSONObject.toJSONString(params), NcgWatch.class);
            return savePart(watch);
        }
    }

    private Result saveAll(NcgWatchVO vo){
        if (ObjectUtil.isEmpty(vo.getId())) {
            // 生成一个UUID作为表主键
            vo.setId(UUID.randomUUID().toString().replaceAll("-", ""));
            NcgWatchLocationInfo locationInfo = vo.getLocationInfo();
            NcgWatchAlarmInfo alarmInfo = vo.getAlarmInfo();
            // 将locationInfo 添加到数据库中
            locationInfo.setId(UUID.randomUUID().toString().replaceAll("-", ""));//  生成主键
            locationInfo.setWatchimei(vo.getImei());
            ncgWatchService.saveLocationInfo(locationInfo);
            // 将alarmInfo 添加到数据库中
            alarmInfo.setId(UUID.randomUUID().toString().replaceAll("-", ""));
            alarmInfo.setWatchimei(vo.getImei());
            ncgWatchService.saveAlarmInfo(alarmInfo);
            // 将 locationInfo 和 alarmInfo 生成的id设置到当前的实体 添加到数据库中
            vo.setLocationInfoid(locationInfo.getId());
            vo.setAlarmInfoid(alarmInfo.getId());
            vo.setCreatetime(LocalDateTime.now());
        } else {
            // 判断 locationInfo对象和 alarmInfo对象是否有值 ncgWatch.getLocationInfo() != null
            if (!ObjectUtils.objectCheckIsNull(vo.getLocationInfo())){
                // 根据 id 查询出绑定的locationInfo对象的id
                vo.getLocationInfo().setId(ncgWatchService.getLocationInfoId(vo.getId()).getId());
                ncgWatchService.setLocationInfo(vo.getLocationInfo());
            }
            if (!ObjectUtils.objectCheckIsNull(vo.getAlarmInfo())){
                // 根据 id 查询出绑定的locationInfo对象的id
                vo.getAlarmInfo().setId(ncgWatchService.getAlarmInfoId(vo.getId()).getId());
                ncgWatchService.setAlarmInfo(vo.getAlarmInfo());
            }
        }
        NcgWatch ncgWatch = new NcgWatch();
        BeanUtil.copyProperties(vo, ncgWatch);
        checkWarning(ncgWatch);
        return Result.success(ncgWatchService.saveOrUpdate(ncgWatch));
    }

    private Result savePart(NcgWatch ncgWatch){
        if (ObjectUtil.isEmpty(ncgWatch.getId())) {
            // 生成一个UUID作为表主键
            ncgWatch.setId(UUID.randomUUID().toString().replaceAll("-", ""));
            NcgWatchLocationInfo locationInfo = new NcgWatchLocationInfo();
            NcgWatchAlarmInfo alarmInfo = new NcgWatchAlarmInfo();
            // 将locationInfo 添加到数据库中

            locationInfo.setId(UUID.randomUUID().toString().replaceAll("-", ""));//  生成主键
            locationInfo.setWatchimei(ncgWatch.getImei());
            ncgWatchService.saveLocationInfo(locationInfo);

            // 将alarmInfo 添加到数据库中
            alarmInfo.setId(UUID.randomUUID().toString().replaceAll("-", ""));
            alarmInfo.setWatchimei(ncgWatch.getImei());
            ncgWatchService.saveAlarmInfo(alarmInfo);

            // 将 locationInfo 和 alarmInfo 生成的id设置到当前的实体 添加到数据库中
            ncgWatch.setLocationInfoid(locationInfo.getId());
            ncgWatch.setAlarmInfoid(alarmInfo.getId());
            ncgWatch.setCreatetime(LocalDateTime.now());
            checkWarning(ncgWatch);
        }
        return Result.success(ncgWatchService.saveOrUpdate(ncgWatch));
    }

    /**
     * 判断当前用户的测试指数是否正常
     * @param ncgWatch
     */
    private void checkWarning(NcgWatch ncgWatch) {
        Warning warning = new Warning();
        Integer flag = 0;
        /**
         *  如果发送的数据是心率
         *  传统的心率的范围一般是心率正常的节律是窦性节律，它的范围在安全状态下是60-100次/分，但正常范围是比较早的研究资料
         *  主要是国外的研究资料得出来的一个正常范围，超过100次/分叫心动过速，正常节律下的心率超过100次/叫窦性心动过速，如果低于60次/分叫窦性心动过缓。
         */
        if (ncgWatch.getHeartRate() != null) {
            if (ncgWatch.getHeartRate() < 60) {
                warning.setWarningType("窦性心动过缓");
                warning.setHeartRate(String.valueOf(ncgWatch.getHeartRate()));
                flag = 1;
            } else if (ncgWatch.getHeartRate() > 100) {
                warning.setWarningType("窦性心动过速");
                warning.setHeartRate(String.valueOf(ncgWatch.getHeartRate()));
                flag = 1;
            } else {
                return;
            }
        }
        /**
         *  舒张压 收缩压
         *  1级高血压:属于轻度高血压收缩压> 140或舒张压> 90
         *  2级高血压:中度高血压收缩压> 160或舒张压> 100
         *  3级高血压:属于重度高血压，收缩压或舒张压> 110 > 180
         */
        if (ncgWatch.getSystolicBloodPressure() != null && ncgWatch.getDiastolicBloodPressure() != null) {
            if (ncgWatch.getSystolicBloodPressure() > 140 && ncgWatch.getDiastolicBloodPressure() > 90) {
                warning.setWarningType("一级高血压");
                warning.setSys(String.valueOf(ncgWatch.getSystolicBloodPressure()));
                warning.setDia(String.valueOf(ncgWatch.getDiastolicBloodPressure()));
                flag = 1;
            } else if (ncgWatch.getSystolicBloodPressure() > 160 && ncgWatch.getDiastolicBloodPressure() > 100) {
                warning.setWarningType("二级高血压");
                warning.setSys(String.valueOf(ncgWatch.getSystolicBloodPressure()));
                warning.setDia(String.valueOf(ncgWatch.getDiastolicBloodPressure()));
                flag = 1;
            } else if (ncgWatch.getSystolicBloodPressure() > 180 && ncgWatch.getDiastolicBloodPressure() > 110){
                warning.setWarningType("三级高血压");
                warning.setSys(String.valueOf(ncgWatch.getSystolicBloodPressure()));
                warning.setDia(String.valueOf(ncgWatch.getDiastolicBloodPressure()));
                flag = 1;
            }  else {
                return;
            }
        }

        /**
         *  血氧
         *  动脉血氧分压正常值是95-100mmHg，动脉血氧饱和度正常值是95%-98%。动脉血氧分压在临床的意义是判断有无缺氧，根据动脉血氧分压的值，低氧血症分为轻度、中度、重度三型
         *  轻度低氧血症氧分压60-80mmHg
         *  中度低氧血症氧分压40-60mmHg
         *  重度低氧血症氧分压小于40mmHg
         */
        if (ncgWatch.getBloodOxygen() != null) {
            if (ncgWatch.getBloodOxygen() > 60 && ncgWatch.getBloodOxygen() < 80) {
                warning.setWarningType("轻度低氧血症");
                warning.setBloodOxygen(String.valueOf(ncgWatch.getBloodOxygen()));
                flag = 1;
            } else if (ncgWatch.getBloodOxygen() > 40 && ncgWatch.getBloodOxygen() >= 60) {
                warning.setWarningType("中度低氧血症");
                warning.setBloodOxygen(String.valueOf(ncgWatch.getBloodOxygen()));
                flag = 1;
            } else if (ncgWatch.getBloodOxygen() <= 40){
                warning.setWarningType("重度低氧血症");
                warning.setBloodOxygen(String.valueOf(ncgWatch.getBloodOxygen()));
                flag = 1;
            }  else {
                return;
            }
        }
        if (ncgWatch.getBodyTemperature() != null) {
            return;
        }
        if (flag == 1) {
            // 根据 IMEI 获取绑定的用户
            QueryWrapper<NcgDeviceWatch> wrapper = new QueryWrapper<>();
            wrapper.eq("imei", ncgWatch.getImei());
            NcgDeviceWatch one = deviceWatchService.getOne(wrapper);
            warning.setId(UUID.randomUUID().toString().replace("-",""));
            warning.setCreatetime(ncgWatch.getCreatetime());
            warning.setImei(ncgWatch.getImei());
            warning.setUid(one != null ? one.getUid() : null);
            warning.setSource("智能手表");
            warningService.save(warning);
        }
    }

    @Transactional
    @ApiOperation(value = "获取结果更新设备信息(locationInfo)", notes = "获取结果更新设备信息(locationInfo)")
    @PostMapping("/getParam/locationInfo")
    public Result saveLocationInfo(@RequestBody NcgWatchLocationInfo locationInfo) {
        try {
            locationInfo.setId(ncgWatchService.getLocationInfoId(locationInfo.getWatchimei()).getId());
            ncgWatchService.setLocationInfo(locationInfo);
            return Result.success("信息更新成功");
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error(Constants.CODE_500, "信息更新失败");
        }
    }

    @Transactional
    @ApiOperation(value = "获取结果更新设备信息(alarmInfo)", notes = "获取结果更新设备信息(alarmInfo)")
    @PostMapping("/getParam/alarmInfo")
    public Result saveAlarmInfo(@RequestBody NcgWatchAlarmInfo alarmInfo) {
        try {
            alarmInfo.setId(ncgWatchService.getAlarmInfoId(alarmInfo.getWatchimei()).getId());
            ncgWatchService.setAlarmInfo(alarmInfo);
            return Result.success("信息更新成功");
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error(Constants.CODE_500, "信息更新失败");
        }
    }

    @ApiOperation(value = "获取所有设备信息", notes = "获取所有设备信息")
    @GetMapping("/getAllWatch")
    public Result getAllWatch() {
        List<NcgWatch> list = ncgWatchService.list();
        List<NcgWatchVO> vos = MyBeanUtil.collectionCopy(list, NcgWatchVO.class);
        vos.forEach(all -> {
            all.setLocationInfo(ncgWatchService.getLocationInfo(all.getImei(), all.getLocationInfoid()));
            all.setAlarmInfo(ncgWatchService.getAlarmInfo(all.getImei(), all.getAlarmInfoid()));
        });
        return Result.success(vos);
    }

    @ApiOperation(value = "获取所有设备信息分页展示", notes = "获取所有设备信息分页展示")
    @GetMapping("/getPageWatch")
    public Result getPageWatch(@RequestParam Integer pageNum, @RequestParam Integer pageSize) {
        QueryWrapper<NcgWatch> wrapper = new QueryWrapper<>();
        wrapper.orderByDesc("createtime");
        Page<NcgWatch> page = ncgWatchService.page(new Page<>(pageNum, pageSize), wrapper);
        List<NcgWatch> list = page.getRecords();
        for (int i = 0; i < list.size(); i++) {
            if (list.get(i).getStepCount() == null && list.get(i).getHeartRate() == null
                    && list.get(i).getRemainElectricity() == null && list.get(i).getSystolicBloodPressure() == null
                    && list.get(i).getDiastolicBloodPressure() == null && list.get(i).getBloodOxygen() == null && list.get(i).getBodyTemperature() == null){
                list.remove(i); // 移除当前对象
            }
        }

        return Result.success(page);
    }

    @ApiOperation(value = "查询设备信息 生成图表数据", notes = "查询设备信息 生成图表数据")
    @PostMapping("/getChart")
    public Result getChart(@RequestBody Map params) {
        Integer pageNum = 1;
        Integer pageSize = 10;
        Page<NcgWatch> list;
        List<NcgWatchVO> vos;
        if (params.size() == 0) {
           return Result.error(Constants.CODE_500, "请发送查询参数");
        } else {
            QueryWrapper<NcgWatch> queryWrapper = new QueryWrapper<>();
            if (params.containsKey("stepCount")){
                queryWrapper.isNotNull("stepCount");
                queryWrapper.gt("stepCount", 0);
            }
            if (params.containsKey("heartRate")){
                queryWrapper.isNotNull("heartRate");
                queryWrapper.gt("heartRate", 0);
            }
            if (params.containsKey("systolicBloodPressure")){
                queryWrapper.isNotNull("systolicBloodPressure");
                queryWrapper.gt("systolicBloodPressure", 0);
            }
            if (params.containsKey("diastolicBloodPressure")){
                queryWrapper.isNotNull("diastolicBloodPressure");
                queryWrapper.gt("diastolicBloodPressure", 0);
            }
            if (params.containsKey("bloodOxygen")){
                queryWrapper.isNotNull("bloodOxygen");
                queryWrapper.gt("bloodOxygen", 0);
            }
            if (params.containsKey("bodyTemperature")){
                queryWrapper.isNotNull("bodyTemperature");
                queryWrapper.gt("bodyTemperature", 0);
            }
            if (params.containsKey("pageNum")){
                pageNum = (Integer) params.get("pageNum");
            }
            if (params.containsKey("pageSize")){
                pageSize = (Integer) params.get("pageSize");
            }
            list = ncgWatchService.page(new Page<>(pageNum, pageSize), queryWrapper);
            vos = MyBeanUtil.collectionCopy(list.getRecords(), NcgWatchVO.class);
            vos.forEach(all -> {
                all.setLocationInfo(ncgWatchService.getLocationInfo(all.getImei(), all.getLocationInfoid()));
                all.setAlarmInfo(ncgWatchService.getAlarmInfo(all.getImei(), all.getAlarmInfoid()));
            });
        }
        List<Object> resultList;
        List<List<Object>> result = new ArrayList<>();
        for (NcgWatchVO vo : vos){
            resultList = new ArrayList<>();
            if (params.containsKey("stepCount")){
                resultList.add(vo.getStepCount());
                resultList.add(vo.getCreatetime());
            }
            if (params.containsKey("heartRate")){
                resultList.add(vo.getHeartRate());
                resultList.add(vo.getCreatetime());
            }
            if (params.containsKey("systolicBloodPressure")){
                resultList.add(vo.getSystolicBloodPressure());
                resultList.add(vo.getCreatetime());
            }
            if (params.containsKey("diastolicBloodPressure")){
                resultList.add(vo.getDiastolicBloodPressure());
                resultList.add(vo.getCreatetime());
            }
            if (params.containsKey("bloodOxygen")){
                resultList.add(vo.getBloodOxygen());
                resultList.add(vo.getCreatetime());
            }
            if (params.containsKey("bodyTemperature")){
                resultList.add(vo.getBodyTemperature());
                resultList.add(vo.getCreatetime());
            }
            result.add(resultList);
        }
        return Result.success(result);
    }

    @GetMapping("/getResult/{path}")
    public Result getParam(@PathVariable String path) {

            try {
            String url = "https://terminal.glxsystem.com/device-api/platform/command/execute";
            //设置请求头信息
            HttpHeaders headers = new HttpHeaders();
            MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
            headers.setContentType(type);
            headers.add("Accept", MediaType.APPLICATION_JSON.toString());
            // 设置请求体
            Map<String, Object> params = new HashMap<>();
            params.put("uuid", "494b8e7308ce16cd0856a3a181148b70");
            params.put("imei", "863995146888083");
            params.put("cmd", path);
            if ("setgps".equals(path)) {
                params.put("cycle", 30);
            }
            //设置body部分
            HttpEntity<String> entity = new HttpEntity<String>(JSON.toJSONString(params), headers);
            RestTemplate restTemplate = new RestTemplate();
            ResponseEntity<String> result = restTemplate.exchange(url, HttpMethod.POST, entity, String.class);
            log.info("The remote interface returns data ==> {}", result.getBody());
            // 将接口返回数据 返回到前端
            return Result.success(result.getBody());
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error(Constants.CODE_500, "系统错误");
        }
    }

    // 条件查询
    @GetMapping("/findConditionPage")
    @ApiOperation(value = "根据设备号查找手表数据", notes = "根据设备号查找手表数据")
    public Result findConditionPage(@RequestParam Map<String, String> params){

        String uid = params.get("uid");

        QueryWrapper<NcgDeviceWatch> uidWrapper = new QueryWrapper<NcgDeviceWatch>()
                .eq(ObjectUtil.isNotEmpty(uid), "uid", uid)
                .eq("type", 5);
        NcgDeviceWatch deviceWatch = deviceWatchService.getOne(uidWrapper);

        if (deviceWatch == null) {

            return Result.error(Constants.CODE_500, "未绑定手表设备");

        }else {

            String imei = deviceWatch.getImei();

            QueryWrapper<NcgWatch> queryWrapper = new QueryWrapper<>();
            queryWrapper.select("imei,ifnull(sum(step_count),0) as stepCount,ifnull(sum(remain_electricity),0) as remainElectricity,ifnull(sum(systolic_blood_pressure),0) as systolicBloodPressure,ifnull(sum(diastolic_blood_pressure),0) as diastolicBloodPressure,ifnull(sum(heart_rate),0) as heartRate,ifnull(sum(blood_oxygen),0) as bloodOxygen,ifnull(sum(body_temperature),0) as bodyTemperature,createtime");
            queryWrapper.eq(ObjectUtil.isNotEmpty(imei), "imei", imei);
            queryWrapper.groupBy("createtime");
            List<NcgWatch> getData =(List<NcgWatch>)ncgWatchService.list(queryWrapper);
            List<NcgWatch> getDatanew = new ArrayList<>();
            for(int i = 0;i<getData.size();i++ ){
                NcgWatch one = getData.get(i);
                if(one.getStepCount() > 0
                        || one.getBloodOxygen() > 0
                        || one.getDiastolicBloodPressure()>0
                        || one.getSystolicBloodPressure() > 0
                        || one.getHeartRate()>0
                        || one.getBodyTemperature().doubleValue()>0
                ){
                    getDatanew.add(one);
                }
            }
            Collections.sort(getDatanew, Comparator.comparing(NcgWatch::getCreatetime).reversed());

            return  Result.success(getDatanew);
        }
    }

    /*@ApiImplicitParams({
            @ApiImplicitParam(name = "deviceMac", value = "设备编码", paramType = "String"),
            @ApiImplicitParam(name = "starttime", value = "开始时间", paramType = "String"),
            @ApiImplicitParam(name = "endtime", value = "结束时间", paramType = "String"),
    })
    @PostMapping("/getPressure")
    public Result getPressure(@RequestBody JSONObject jsonObject){
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String url = "http://taiyibp.tjtzkt.com/getBpDatas.aspx";
            // 设置请求体
            Map<String, Object> params = new HashMap<>();
            params.put("deviceMac", jsonObject.get("deviceMac"));
            params.put("starttime", jsonObject.get("starttime"));
            params.put("endtime", jsonObject.get("endtime"));
            String param = JSON.toJSONString(params);
            String result = HttpUtils.sendPost(url, param);
            // 将获取到的返回数据转成 json格式数据
            JSONObject jsonObject1 = JSONObject.parseObject(result);
            // 从json中获取data对应的数据
            List<Object> data = (List<Object>) jsonObject1.get("data");
            System.out.println(data);
            List<Saihong> saihongs = new ArrayList<>();
            for (int i = 0; i < data.size(); i++) {
                Saihong saihong = new Saihong();
                BeanUtil.copyProperties(data.get(i), saihong);
                saihongs.add(saihong);
            }
            for (Saihong saihong : saihongs) {
                saihongService.save(saihong);
            }
            return Result.success(data);
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error(Constants.CODE_500, "系统错误");
        }

    }*/

}
